<?php
namespace app\Support;

use think\facade\Cache;
use app\model\sms as sms_model;
use App\Support\http;

class sms
{
    // 配置信息
    protected $config = [];

    // 每天发送短信限制
    protected $send_day_limit = 5;

    // 发送间隔
    protected $send_interval = 60;

    // 验证码有效期
    protected $code_expire = 1800;

    // http工具
    protected $http;

    public function __construct()
    {
        $this->http = new http();

        $this->config = config( 'sms' );    // 获取配置

        $this->day_send_limit = site_config( 'sms_send_day_limit' );    // 日发送限制配置

        $this->send_interval = site_config( 'sms_send_interval' );  // 发送间隔配置

        $this->code_expire = site_config( 'sms_code_expire' );  // 验证码有效期配置
    }

    /**
     * 发送验证码
     * 
     * @param string $number 验证码数字
     * @param int $referrer 来源
     * @param int $scenes 应用场景
     * @param string $code 验证码
     * @return bool 是否发送成功
     */
    public function send_code( $phone, $referrer, $scenes, $code ): Bool
    {
        // 初始化redis
        $redis = Cache::store( 'redis' )->handler();
        
        // 查询发送间隔限制
        if( $redis->exists( 'sms_send_interval:' . $phone ) )
        {
            throw new \app\Exception( '发送频率过快，请稍后再试', 1 );
        }

        // 查询发送数量限制
        if( $count = $redis->exists( 'sms_send_day_limit:' . $phone ) )
        {
            if( $count >= $this->day_send_limit )
            {
                throw new \app\Exception( '您今天发送的次数超过限制,请联系管理员', 2 );
            }
        }

        // 发送短信
        $content = $this->config[ 'signature' ] . '您本次的验证码为：' . $code;  // 短信内容
        $response = $this->send( $phone, $content );

        // 发送结果
        $status = '-1';
        if( $result = json_decode( $response, true ) )
        {
            if( $result[ 'code' ] == 0 )
            {
                $status = 1;
            }
        }

        // 记录发送
        sms_model::create( [
            'referrer' => $referrer,    // 来源
            'scenes' => $scenes,        // 应用场景
            'phone' => $phone,          // 手机号
            'content' => $code,         // 发送内容
            'response' => $response,    // 响应数据
            'status' => $status,        // 发送结果
            'send_time' => time()       // 发送时间
        ] );

        // 记录发送有效期
        $redis->setex( 'sms_code:' . $phone, $this->code_expire, $code );    // 记录验证码有效期

        // 日发送次数限制
        $sms_send_day_limit_key = 'sms_send_day_limit:' . $phone;
        if( $redis->exists( $sms_send_day_limit_key ) && ( $redis->ttl( $sms_send_day_limit_key ) > 0 ) )
        {
            $redis->incr( $sms_send_day_limit_key );
        }else{
            // 当天0点取消
            $over_time = strtotime( date( 'Y-m-d 23:59:59', time() ) ) + 1 - time();
            $redis->setex( $sms_send_day_limit_key, $over_time, 1 );
        }

        return $status == 1? true: false;
    }

    /**
     * 发送短信
     * 
     * @param string $phone 发送手机号
     * @param string $content 发送数据
     * @return string
     */
    protected function send( $phone, $content )
    {
        // 初始化短信发送数据
        $data = array();
        $data[ 'type' ] = 'send';                                                      // 发送方式 
        $data[ 'username' ] = $this->config[ 'username' ];                             // 用户名
        $data[ 'password' ] = strtoupper( md5( $this->config[ 'password' ] ) );        // 密码( 大写md5加密后的密码 )
        $data[ 'gwid' ] = $this->config[ 'gateway' ];                                  // 网关
        $data[ 'mobile' ] = $phone;                                                    // 发送手机号
        $data[ 'message' ] = $content;                                                 // 发送信息
        $data[ 'rece' ] = 'json';                                                      // 返回数据类型

        //开始请求短信接口
        return $this->http->post( $this->config[ 'api' ], $data );
    }
}